package jmine.tec.proxy;

import java.io.Serializable;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

/**
 * 
 * @author takeshi
 *
 */
public class SynchronizedInvocationHandler implements InvocationHandler, Serializable {

    private static final long serialVersionUID = 4149983783437990262L;

    private final Object delegate;
	
	private final Object lock;
	
	/**
	 * 
	 * @param delegate the Object to wictch delegate method calls
	 * @param lock the Object to witch lock
	 */
	public SynchronizedInvocationHandler(final Object delegate, final Object lock) {
		super();
		this.delegate = delegate;
		this.lock = lock;
	}

	/**
	 * 
	 * @param delegate the Object to wictch delegate method calls
	 */
	public SynchronizedInvocationHandler(final Object delegate) {
		this(delegate, new Object());
	}	

	/**
	 * @param proxy the proxy object
	 * @param method the method being invoked
	 * @param args the arguments
	 * @throws Throwable throwable
	 * @return {@link Object}
	 * 
	 */
	public Object invoke(final Object proxy, final Method method, final Object[] args) throws Throwable {
		synchronized (lock) {
            try {
                return method.invoke(delegate, args);
            } catch (InvocationTargetException e) {
                if (e.getCause() != null) {
                    throw e.getCause();
                } else {
                    throw e.getTargetException();
                }
            }
		}
	}
}
